﻿using Extensions.Attributes;
using GraphQL;
using GraphQL.Http;
using GraphQL.Types;
using GraphQLDomain.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

namespace Management.Controllers
{
    [Route("/graphql")]
    [ApiController]
    public class GraphQLController : ControllerBase
    {
        private readonly ISchema schema;
        private readonly IDocumentExecuter executer;
        private readonly IDocumentWriter writer;

        public GraphQLController(ISchema schema, IDocumentExecuter executer, IDocumentWriter writer)
        {
            this.schema = schema;
            this.executer = executer;
            this.writer = writer;
        }
        /// <summary>
        /// GraphQL的端口
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [HiddenAPI]
        public async Task Post()
        {
            var request = await DeserializeAsync<GraphQLRequest>(HttpContext.Request.Body);

            var result = await executer.ExecuteAsync(options =>
            {
                options.Schema = schema;
                options.Query = request?.Query;
                options.OperationName = request.OperationName;
                options.Inputs = request?.Variables.ToInputs();
                //options.UserContext = 
                //options.EnableMetrics = 
            });
            await WriteResponseAsync(HttpContext, result);
        }


        private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;

            await writer.WriteAsync(context.Response.Body, result);
        }

        private async Task<T> DeserializeAsync<T>(Stream stream)
        {

            using (var reader = new StreamReader(stream))
            {
                var result = await reader.ReadToEndAsync();
                return JsonConvert.DeserializeObject<T>(result);
            }
        }


    }
}